package com.atguigu.gmall.consumer;

import com.atguigu.gmall.constant.MqConst;
import com.atguigu.gmall.constant.RedisConst;
import com.atguigu.gmall.entity.SeckillProduct;
import com.atguigu.gmall.entity.UserSeckillSkuInfo;
import com.atguigu.gmall.search.Product;
import com.atguigu.gmall.service.SeckillService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Component
public class SeckillConsumer {

    @Autowired
    private SeckillService seckillService;
    @Autowired
    private RedisTemplate redisTemplate;

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.SCAN_SECKILL_EXCHANGE, durable = "false", autoDelete = "true"),
            key = {MqConst.SCAN_SECKILL_ROUTE_KEY},
            value = @Queue(value = MqConst.SCAN_SECKILL_QUEUE, durable = "false")
    ))
    public void scanSeckillProductToRedis(Channel channel, Message message) throws IOException {
        //查询数据库中今日秒杀的商品
        List<SeckillProduct> seckillProducts = seckillService.findSeckillProduct();
        if (!CollectionUtils.isEmpty(seckillProducts)){
            for (SeckillProduct seckillProduct : seckillProducts) {
                //检查redis中是否已经存在秒杀的商品
                boolean flag = redisTemplate.boundHashOps(RedisConst.SECKILL_PRODUCT).hasKey(seckillProduct.getSkuId().toString());
                if (flag)
                    continue; //如果由就跳过
                //如果没有，就存储到redis上
                redisTemplate.boundHashOps(RedisConst.SECKILL_PRODUCT).put(seckillProduct.getSkuId().toString(), seckillProduct);
                //4.利用list的数据结构存储库存数量 （减库存的时候吐出一个 防止超卖）
                for (Integer integer = 0; integer < seckillProduct.getNum(); integer++) {
                    redisTemplate.boundListOps(RedisConst.SECKILL_STOCK_PREFIX +seckillProduct.getSkuId())
                            .leftPush(seckillProduct.getSkuId().toString());
                }
                //5.通知redis集群中其他节点该商品可以进行秒杀了 状态位
                redisTemplate.convertAndSend(RedisConst.PREPARE_PUB_SUB_SECKILL,seckillProduct.getSkuId()+":"+RedisConst.CAN_SECKILL);
            }
        }
        //手动应答
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.PREPARE_SECKILL_EXCHANGE, durable = "false", autoDelete = "true"),
            key = {MqConst.PREPARE_SECKILL_ROUTE_KEY},
            value = @Queue(value = MqConst.PREPARE_SECKILL_QUEUE, durable = "false")
    ))
    public void prepareSeckill(UserSeckillSkuInfo userSeckillSkuInfo, Channel channel, Message message) throws IOException {
        if(userSeckillSkuInfo!=null){
            //开始处理预下单
            seckillService.prepareSeckill(userSeckillSkuInfo);
        }
        //手动应答
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
    //3.清理redis里面的信息
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.CLEAR_REDIS_QUEUE,durable = "false"),
            exchange = @Exchange(value = MqConst.CLEAR_REDIS_EXCHANGE,durable = "false",autoDelete = "true"),
            key = {MqConst.CLEAR_REDIS_ROUTE_KEY}
    ))
    public void clearRedis(Message message, Channel channel) throws Exception{
        QueryWrapper<SeckillProduct> wrapper = new QueryWrapper<>();
        //1为秒杀商品
        wrapper.eq("status",1);
        wrapper.le("end_time",new Date());
        //获取到秒杀结束之后的商品数据
        List<SeckillProduct> seckillProductList = seckillService.list(wrapper);
        for (SeckillProduct seckillProduct : seckillProductList) {
            //删除库存数
            redisTemplate.delete(RedisConst.SECKILL_STOCK_PREFIX + seckillProduct.getSkuId());
        }
        //删除秒杀商品信息
        redisTemplate.delete(RedisConst.SECKILL_PRODUCT);
        //删除用户抢得预售订单
        redisTemplate.delete(RedisConst.PREPARE_SECKILL_USERID_ORDER);
        // 删除用户秒杀最终抢到的订单
        redisTemplate.delete(RedisConst.BOUGHT_SECKILL_USER_ORDER);
        // 更新数据 更新状态 1 表示秒杀开始，2 表示秒杀结束
        SeckillProduct seckillProduct = new SeckillProduct();
        seckillProduct.setStatus("2");
        seckillService.update(seckillProduct,wrapper);
        // 消息确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
}
